/**
 * 
 */
package prj3;

/**
 * Implements the algorithm to calculate the temperature for new cells
 * @author romain
 *
 */
public class EarthAlgorithm implements IAlgorithm {

	
	public EarthAlgorithm(EarthGrid myGrid) {
		this.myGrid = myGrid;
		radius = this.myGrid.getRadius();
		longiMax = this.myGrid.getMaximumLongitude();
		latiMax = this.myGrid.getMaximumLatitude();
	}

	/* Protected variables */
	protected EarthGrid myGrid;
	protected float radius;
	protected int longiMax, latiMax;
	protected boolean prevSet = false;
	protected float prevValue = 0;
	protected float totalArea = 0;
	
	/* (non-Javadoc)
	 * @see prj3.prj2.IAlgorithm#updateGrid()
	 */
	public void updateGrid() {
		
		float totalHeat = 0;
		float totalCool = 0;
		float totalValue = 0;
		
		/* Iterate over all cells */
		for(int longi=0; longi < longiMax; longi++) {
			for(int lati=1; lati <= latiMax; lati++) {
				EarthCell cell = (EarthCell)myGrid.getCellForCoordinate(new SphericalCoordinate(myGrid, radius, longi, lati));
				
				/* Get all four neighbors */
				EarthCell top = (EarthCell)myGrid.getCellForCoordinate((SphericalCoordinate)myGrid.getNeighbor(cell.getCoordinate(), ICoordinate.DIR_TOP));
				EarthCell bottom = (EarthCell)myGrid.getCellForCoordinate((SphericalCoordinate)myGrid.getNeighbor(cell.getCoordinate(), ICoordinate.DIR_BOTTOM));
				EarthCell left = (EarthCell)myGrid.getCellForCoordinate((SphericalCoordinate)myGrid.getNeighbor(cell.getCoordinate(), ICoordinate.DIR_LEFT));
				EarthCell right = (EarthCell)myGrid.getCellForCoordinate((SphericalCoordinate)myGrid.getNeighbor(cell.getCoordinate(), ICoordinate.DIR_RIGHT));
				
				float leftAddition = left.getValue()*cell.getSideLength(ICoordinate.DIR_LEFT);
				float rightAddition = right.getValue()*cell.getSideLength(ICoordinate.DIR_RIGHT);
				//System.out.print("Left value: " + left.getValue() + " Right value: " + right.getValue());
				
				if(!prevSet) {
					prevValue += cell.getValue();
					totalArea += cell.getArea();
				}
				
				float topAddition = 0;
				float bottomAddition = 0;
				if(top != null) {
					topAddition = top.getValue()*cell.getSideLength(ICoordinate.DIR_TOP);
				//	System.out.println(" Top value: " + top.getValue());
				}
				if(bottom != null) {
					bottomAddition = bottom.getValue()*cell.getSideLength(ICoordinate.DIR_BOTTOM);
				//	System.out.println(" Bottom value: " + bottom.getValue());
				}
                //System.out.println("leftAddition = " + leftAddition);
                
				float newValue = (leftAddition + rightAddition + topAddition + bottomAddition)/((float)cell.getTotalSideLength());
				// System.out.print(" GIVES: " + newValue);
               // System.out.println();
				//System.out.println("NeighborHeat = " + newValue);
                
                newValue += cell.getExtraHeating();
                
                totalHeat += cell.getExtraHeating();
                //System.out.println("Heating = " + cell.getExtraHeating());
                //System.out.print("Long: " + longi + ", Lat: " + lati + ", ExtraHeating: " + cell.getExtraHeating());
				//System.out.println(" Cooling: " + EarthCell.getCooling()*cell.getArea());
				
				newValue -= EarthCell.getCooling()*cell.getArea();
				
				totalCool += EarthCell.getCooling()*cell.getArea();
				totalValue += newValue;
                //System.out.println("Cooling = " + EarthCell.getCooling()*cell.getArea());
				//System.out.println("Result: " + newValue);
				cell.setHistoryValue(newValue);
			}
		}
		
		prevSet = true;
		
		System.out.println("Cool " + totalCool + " Heat: " + totalHeat +  " Prev " + prevValue + " Total " + totalValue);
		
		/* Correct heat and cool 
		 */
		float toCorrect = (totalValue - prevValue)/totalArea;
		totalValue = 0;
		for(int longi=0; longi < longiMax; longi++) {
			for(int lati=1; lati <= latiMax; lati++) {
				EarthCell cell = (EarthCell)myGrid.getCellForCoordinate(new SphericalCoordinate(myGrid, radius, longi, lati));
				float value = cell.getHistoryValue();
				value -= toCorrect*cell.getArea();
				cell.setHistoryValue(value);
				totalValue+= value;
			}
		}
		System.out.println("Cool " + totalCool + " Heat: " + totalHeat +  " Prev " + prevValue + " Total " + totalValue);
		/* Switch all values */
		for(int longi=0; longi < longiMax; longi++) {
			for(int lati=1; lati <= latiMax; lati++) {
                while(!	((EarthCell)myGrid.getCellForCoordinate(new SphericalCoordinate(myGrid, radius, longi, lati))).switchValues()){
                    try {
                        //System.out.println("Buffer Full: Long: " + longi + ", Lat: " + lati);
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
			}
		}
	}
}
